package sfsoftware.game.actor.enemy;

import java.util.ArrayList;

import sfsoftware.game.trevor.Enemy;
import sfsoftware.util.Tile;
import sfsoftware.util.Updatable;

public class PathFinder extends Enemy implements Updatable {

	private ArrayList<Tile> openList = new ArrayList<Tile>();
	private ArrayList<Tile> closedList = new ArrayList<Tile>();
	
	public PathFinder(int destX, int destY, String texture, int srcX, int srcY,	int destWidth, int destHeight, Tile[][] assocTileMap) {
		super(destX, destY, texture, srcX, srcY, destWidth, destHeight);
		setSpeed(2);
		tileMap = assocTileMap;	
	}

	private int getFCost(int x, int y, int targetX, int targetY)
	{
		int h = Math.abs(x - targetX) + Math.abs(y - targetY);
		int g = closedList.size();
		
		return h + g;
	}
    private Tile lowestFInOpen(int targetX, int targetY) {
        // TODO currently, this is done by going through the whole openList!
        Tile cheapest = openList.get(0);
        int x = (int) tileMap[targetX][targetY].getX();
        int y = (int) tileMap[targetX][targetY].getY();
        
        for (int i = 0; i < openList.size(); i++) 
        {
        	Tile t = openList.get(i);
        	if(getFCost((int)t.getX(),(int)t.getY(),targetX, targetY) < getFCost((int)cheapest.getX(),(int)cheapest.getY(),targetX, targetY))
            {
        	
                cheapest = openList.get(i);
            }
        }
        return cheapest;
    }
	
	private void addNode(int x, int y)
	{
		
		/*if (this neighbor is in the closed list and our current g value is lower) {
            update the neighbor with the new, lower, g value 
            change the neighbor's parent to our current node
        }
        else if (this neighbor is in the open list and our current g value is lower) {
            update the neighbor with the new, lower, g value 
            change the neighbor's parent to our current node
        }
        else this neighbor is not in either the open or closed list {
            add the neighbor to the open list and set its g value
        }*/
		
		if(!(closedList.contains(tileMap[x][y])) && tileMap[x][x].isWalkable())
		{
			if(!(openList.contains(tileMap[x][y])))
			{
				openList.add(tileMap[x][y]);
			}
			else
			{
				
			}
					
		}
	}
	
	private ArrayList<Tile> findPath(int startX, int startY, int targetX, int targetY)
	{
		openList.clear();
		closedList.clear();
		
		// Add the current location to the open list
		openList.add(tileMap[startX][startY]);
		int currentX = startX;
		int currentY = startY;
		
		while(!(openList.isEmpty()))
		{
			// consider the best node in the open list (the node with the lowest f value)			
			Tile current =  lowestFInOpen(targetX, targetY);
			
			// Add the current tile to the closed list and remove it from the open list
			closedList.add(current);
			openList.remove(current);			
			
			if(closedList.contains(tileMap[targetX][targetY]))
			{
				// If the closed list contains the target tile, we found the path!
				return closedList;
			}
			else
			{
				/* move the current node to the closed list and consider all of its neighbors
           		closedList.add(currentX, currentY);
           		addNode(currentX + 1, currentY);
           		addNode(currentX, currentY + 1);
           		addNode(currentX - 1, currentY);
           		addNode(currentX, currentY - 1);
           		*/
			}
		}
		
		return null;
	}
	
	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}

}
